package br.com.afi.pattern.dao;
import java.io.Serializable;
import java.util.List;

import br.com.afi.pattern.model.Model;

/**
 * Essa interface possui os métodos genéricos para DAOs.
 *
 * @author Hibernate
 * @version 1.0
 * @param <E> Tipo da Entity
 * @param <ID> Tipo da chave primária da Entity.
 */
public interface GenericDAO<E extends Model<ID>, ID extends Serializable>
{
	/**
	 * Obtém a quantidade total de entities
	 * 
	 * @return Quantidade de entities
	 */
	Number countAll();

	/**
	 * Busca um registro através da sua chave primária.
	 * 
	 * @param id Chave primária
	 * @param lock Se verdadeiro, trava a tabela para execução de updates.
	 * @return Entity
	 */
	E findById( ID id, boolean lock );
	
	/**
	 * Busca um registro através da sua chave primária.
	 * 
	 * @param id Chave primária
	 * @return Entity
	 */
	E findById( ID id );

	/**
	 * Busca todos os registros.
	 * 
	 * @return Lista de Entitys
	 */
	List<E> findAll();

	/**
	 * Busca todos os registros utilizando paginação.
	 * 
	 * @param firstResult Número do primeiro registro.
	 * @param maxResults Número máximo de registros.
	 * @return Lista de entidades
	 */
	List<E> findAll( int firstResult, int maxResults );

	/**
	 * Verifica se existe algum registro no banco que possui o Id informado.
	 * 
	 * @param id Id
	 * @return Verdadeiro se existir um registro no banco com o Id informado
	 */
	boolean existsById( ID id );

	/**
	 * Insere ou atualiza o registro que representa entity no banco de dados.
	 * 
	 * @param entity Entity
	 * @return Entity
	 */
	E makePersistent( E entity );

	/**
	 * Remove o registro que representa a Entity no banco de dados.
	 * 
	 * @param entity Entity
	 */
	void makeTransient( E entity );

	/**
	 * Obtém a quantidade de registro buscando pela instância informada.
	 * 
	 * @param exampleInstance Instância de exemplo
	 * @param excludeProperty Propriedades a serem desconsideradas na busca
	 * @return Lista de Entitys
	 */
	Number countByExample( E exampleInstance, String... excludeProperty );

	/**
	 * Obtém a quantidade de registro buscando pela instância informada utilizando like.
	 * 
	 * @param exampleInstance Instância de exemplo
	 * @param includeRelationships Incluir relacionamentos na busca?
	 * @param excludeProperty Propriedades a serem desconsideradas durante na busca
	 * @return Lista de entidades
	 */
	Number countByExampleILike( E exampleInstance, boolean includeRelationships, String... excludeProperty );

	/**
	 * Busca por um instância de exemplo.
	 * 
	 * @param exampleInstance Instância de exemplo
	 * @param excludeProperty Propriedades a serem desconsideradas durante na busca
	 * @return Lista de entidades
	 */
	List<E> findByExample( E exampleInstance, String... excludeProperty );

	/**
	 * Busca por um instância de exemplo utilizando like.
	 * 
	 * @param exampleInstance Instância de exemplo
	 * @param excludeProperty Propriedades a serem desconsideradas durante na busca
	 * @return Lista de entidades
	 */
	List<E> findByExampleILike( E exampleInstance, String... excludeProperty );

	/**
	 * Busca por um instância de exemplo utilizando insensitive like.
	 * 
	 * @param exampleInstance Instância de exemplo
	 * @param includeRelationships Incluir relacionamentos na busca?
	 * @param excludeProperty Propriedades a serem desconsideradas durante na busca
	 * @return Lista de entidades
	 */
	List<E> findByExampleILike( E exampleInstance, boolean includeRelationships, String... excludeProperty );

	/**
	 * Busca por um instância de exemplo utilizando insensitive like e paginação
	 * 
	 * @param exampleInstance Instância de exemplo
	 * @param includeRelationships Incluir relacionamentos na busca?
	 * @param firstResult Número do primeiro registro
	 * @param maxResults Número máximo de registros
	 * @param excludeProperty Propriedades a serem desconsideradas durante na busca
	 * @return Lista de entidades
	 */
	List<E> findByExampleILike( E exampleInstance, boolean includeRelationships, int firstResult, int maxResults, String... excludeProperty );
}
